package com.test.cordova.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;

import com.test.cordova.R;
import com.test.cordova.util.Logger;
import com.test.cordova.util.ScreenUtil;

/**
 * 练习自定义View
 */

public class CustomCircleImage extends AppCompatImageView {

    private static final String TAG = CustomCircleImage.class.getSimpleName();
    private int bgColor = Color.TRANSPARENT ;
    private Matrix matrix = new Matrix();
    private Paint mBitPaint = new Paint();
    private Paint mCircleBackgroundPaint = new Paint();
    private int radius;
    private RectF bgRect = new RectF();
    private RectF mDrawableRect = new RectF();
    private BitmapShader shader;
    private Bitmap bitmap;
    private int bitmapWidth;
    private int bitmapHeight;
    private int height;
    private int width;
    private Paint progressBarPaint;
    private Paint outlinePaint;
    private float bitC; //周长
    private Paint wavePaint;
    private float[] mYPosition;
    private float[] mYPosition1;
    private float[] mYPosition2;
    private float mCycleFactorW;

    private Context mContext;
    public CustomCircleImage(Context context) {
        super(context);
        mContext = context;
        init();
    }

    public CustomCircleImage(Context context, @Nullable AttributeSet attrs) {
        this(context,attrs,0);
    }

    public CustomCircleImage(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomCircleImage, defStyleAttr, 0);
        bgColor = typedArray.getColor(R.styleable.CustomCircleImage_bg_color, bgColor);
        typedArray.recycle();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int heigthMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        Logger.e(TAG+" onMeasure","width "+width+" height: "+height);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 监听测量结束
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        width = w ;
        height = h ;
        Logger.e(TAG+" onSizeChanged","width "+w+" height: "+h+ "getWidth: "+getWidth()+" getHeight: "+getHeight()+" getPaddingRight:"+getPaddingRight()+" getPaddingTop: "+getPaddingTop());
        super.onSizeChanged(w, h, oldw, oldh);
        init();
        initProgressPaint();
        initWaveProgressPaint();
    }

    private void initWaveProgressPaint() {
        wavePaint = new Paint();
        wavePaint.setAntiAlias(true);
        wavePaint.setStyle(Paint.Style.STROKE);
        wavePaint.setColor(getResources().getColor(R.color.lightgray));
        //存储原始波纹数据
        mYPosition = new float[width];

        mYPosition1 = new float[width];
        mYPosition2 = new float[width];

        // 将周期定为view总宽度
        mCycleFactorW = (float) (2 * Math.PI / width);
        for (int i = 0; i <  width; i++) {
            // 10 影响波峰高度
            mYPosition[i] = (float) (10 * Math.sin(mCycleFactorW * i));
        }

        mXOffsetSpeedOne = ScreenUtil.dip2px(mContext,2);
        mXOffsetSpeedTwo =  ScreenUtil.dip2px(mContext,1);

    }


    private void init() {
        super.setScaleType(ScaleType.CENTER_CROP);
        bitmap = ((BitmapDrawable) getDrawable()).getBitmap();
        if (getWidth() == 0 && getHeight() == 0) {
            return;
        }
        if (bitmap == null) {
            invalidate();
            return;
        }

        shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        bitmapHeight = bitmap.getHeight();
        bitmapWidth = bitmap.getWidth();

        mBitPaint.setAntiAlias(true);
        mBitPaint.setShader(shader);

        mCircleBackgroundPaint.setStyle(Paint.Style.FILL);
        mCircleBackgroundPaint.setAntiAlias(true);
        mCircleBackgroundPaint.setColor(bgColor);


        bgRect.set(calculateBounds());
        mDrawableRect.set(bgRect);

        radius = (int)(Math.min(bgRect.width(),bgRect.height())) >> 1;


        /*float max = Math.max(( bgRect.width()/ bitmap.getWidth()), (bgRect.height() / bitmap.getHeight()));
        matrix.setScale(max,max);
        shader.setLocalMatrix(matrix);*/

        updateShaderMatrix();
        invalidate();
    }

    private void initProgressPaint() {
        //进度线
        progressBarPaint = new Paint();
        progressBarPaint.setColor(getResources().getColor(
                android.R.color.holo_green_dark));
        progressBarPaint.setStrokeWidth(12);
        progressBarPaint.setAntiAlias(true);
        progressBarPaint.setDither(true);
        progressBarPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        //progressBarPaint.setStrokeJoin(Paint.Join.ROUND);
        //progressBarPaint.setStrokeCap(Paint.Cap.ROUND);
        progressBarPaint.setStyle(Paint.Style.STROKE);

        //背景线
        outlinePaint = new Paint();
        outlinePaint.setColor(getResources().getColor(
                android.R.color.white));
        outlinePaint.setStrokeWidth(12);
        outlinePaint.setAntiAlias(true);
        outlinePaint.setStyle(Paint.Style.STROKE);

        bitC = (width+height) << 1;
    }

    private RectF calculateBounds() {
        int availableWidth  = getWidth() - getPaddingLeft() - getPaddingRight();
        int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom();

        int sideLength = Math.min(availableWidth, availableHeight);

        float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;
        float top = getPaddingTop() + (availableHeight - sideLength) / 2f;

        return new RectF(left, top, left + sideLength, top + sideLength);
    }

    private void updateShaderMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;

        matrix.set(null);

        if (bitmapWidth * mDrawableRect.height() > mDrawableRect.width() * bitmapHeight) {
            scale = mDrawableRect.height() / (float) bitmapHeight;
            dx = (mDrawableRect.width() - bitmapWidth * scale) * 0.5f;
        } else {
            scale = mDrawableRect.width() / (float) bitmapWidth;
            dy = (mDrawableRect.height() - bitmapHeight * scale) * 0.5f;
        }

        matrix.setScale(scale, scale);
        matrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);

        shader.setLocalMatrix(matrix);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制圆形背景
        canvas.drawCircle(bgRect.centerX(),bgRect.centerY(),radius,mCircleBackgroundPaint);
        //绘制bitmap
        canvas.drawCircle(bgRect.centerX(),bgRect.centerX(),radius,mBitPaint);
        //绘制背景线
        canvaProgressBG(canvas);
        //画进度线
        drawRectProgress(canvas);

        //绘制水波纹
        resetPositonY();
        float tempProgress = height - (height / 100) * progress;
        for (int i = 0; i < width; i++) {
            // 减400只是为了控制波纹绘制的y的在屏幕的位置，大家可以改成一个变量，然后动态改变这个变量，从而形成波纹上升下降效果
            // 绘制第一条水波纹
            canvas.drawLine(i, height - mYPosition1[i] - tempProgress, i, height, wavePaint);
                         // 绘制第二条水波纹
            canvas.drawLine(i, height - mYPosition2[i] - tempProgress, i, height, wavePaint);
        }

        // 改变两条波纹的移动点
         mXOneOffset += mXOffsetSpeedOne;
         mXTwoOffset += mXOffsetSpeedTwo;

        // 如果已经移动到结尾处，则重头记录
        if (mXOneOffset >= width) {
            mXOneOffset = 0;
        }
         if (mXTwoOffset > width) {
             mXTwoOffset = 0;
         }
        //赋予水波纹动感 缺少会卡顿
         postInvalidate();
    }
    private int mXOffsetSpeedOne;
    private int mXOffsetSpeedTwo;
    private int mXOneOffset;
    private int mXTwoOffset;

    private void resetPositonY() {
        // mXOneOffset代表当前第一条水波纹要移动的距离
         int yOneInterval = mYPosition.length - mXOneOffset;
         // 使用System.arraycopy方式重新填充第一条波纹的数据
         System.arraycopy(mYPosition, mXOneOffset, mYPosition1, 0, yOneInterval);
         System.arraycopy(mYPosition, 0, mYPosition1, yOneInterval, mXOneOffset);

         int yTwoInterval = mYPosition.length - mXTwoOffset;
         System.arraycopy(mYPosition, mXTwoOffset, mYPosition2, 0, yTwoInterval);
         System.arraycopy(mYPosition, 0, mYPosition2, yTwoInterval, mXTwoOffset);
    }

    private void drawRectProgress(Canvas canvas) {
        float lineLength = (bitC / 100) * progress;  //图片周长bitC 平分100份,计算进度所在的长度
        float widthHalf = width >> 1; //从top中间开始绘制进度线条
        Logger.e(TAG,"lineLength: "+lineLength+" widthHalf "+widthHalf+" bitC: "+bitC);
        Path linePath = new Path();
        //绘制 topRight线
        if (lineLength < widthHalf) {
            //绘制topline
            linePath.moveTo(widthHalf, 0);
            linePath.lineTo((widthHalf+lineLength), 0);
            canvas.drawPath(linePath,progressBarPaint);
        }
        //绘制 rightLine 线
        if (lineLength > widthHalf) {
            float rightLine = lineLength - widthHalf;
            if (rightLine <= height) {
                linePath.moveTo(widthHalf, 0);
                linePath.lineTo(width, 0);
                linePath.lineTo(width,rightLine);
            }
            canvas.drawPath(linePath,progressBarPaint);
        }
        //绘制 bottomLine 线
        if (lineLength > (widthHalf + height)) {
            float bottomLine = lineLength - widthHalf - height;
            if (bottomLine <= width) {
                linePath.moveTo(widthHalf, 0);
                linePath.lineTo(width, 0);
                linePath.lineTo(width, height);
                linePath.lineTo((width-bottomLine),height);
            }
            canvas.drawPath(linePath,progressBarPaint);
        }
        //绘制 leftLine 线
        if (lineLength > (widthHalf + height+ width)) {
            float leftLine = lineLength - widthHalf - height -width;
            if (leftLine <= height) {
                linePath.moveTo(widthHalf, 0);
                linePath.lineTo(width, 0);
                linePath.lineTo(width, height);
                linePath.lineTo(0,height);
                linePath.lineTo(0,(height-leftLine));
            }
            canvas.drawPath(linePath,progressBarPaint);
        }
        //绘制 topLeft 线
        if (lineLength > (widthHalf + height*2 + width)) {
            float topLine = lineLength - widthHalf -2 * height -width;
            if (topLine <= widthHalf) {
                linePath.moveTo(widthHalf, 0);
                linePath.lineTo(width, 0);
                linePath.lineTo(width, height);
                linePath.lineTo(0,height);
                linePath.lineTo(0,0);
                linePath.lineTo(topLine,0);
            }
            canvas.drawPath(linePath,progressBarPaint);
        }
    }

    private void canvaProgressBG(Canvas canvas) {
        Path linePath = new Path();
        linePath.moveTo(width>>1,0);
        linePath.lineTo(width,0);
        linePath.lineTo(width,height);
        linePath.lineTo(0,height);
        linePath.lineTo(0,0);
        linePath.lineTo(width>>1,0);
        canvas.drawPath(linePath,outlinePaint);
    }

    private float progress;
    public void setProgress(float progress){
        this.progress = progress;
        this.invalidate();
    }

}
